/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.search; import java.awt.*; import java.beans.*; import java.util.*; import org.openide.*; import org.openide.nodes.*; import org.openide.util.*; import org.openidex.search.*; import org.netbeans.modules.search.res.*; /** * Represent one criterion during customization. The criterion * may be in different states: [un]modified. Also links the criterion * with its customizer and storage of own presets. * * <p>Listens: <every property on customized bean> * <p>Fires: PROP_CUSTOMIZED, PROP_STATE * * @author Petr Kuzel * @version */ public class CriterionModel implements PropertyChangeListener { /** ID of predefined system type. */ public final static String DO_NOT_APPLY = Res.text("DO_NOT_APPLY"); // NOI18N public final static String APPLY = Res.text("APPLY"); // NOI18N /** Customized property name. */ public static final String PROP_CUSTOMIZED = "customized"; private boolean modified; /** Inner state property name. */ public static final String PROP_STATE = "state"; private String state; private static final String MODIFICATOR_SUFFIX = " *"; private PresetModel presetModel; private SearchType criterion; private CriteriaModel parent; private Class type; // beaninfo of criterion and customizer obtained from it private BeanInfo beanInfo; private Customizer customizer; private Component customizerComponent; /** Utility field used by bound properties. */ private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport (this); /** Creates new PresetModel */ public CriterionModel(CriteriaModel parent, Class type) { state = DO_NOT_APPLY; modified = false; this.parent = parent; this.type = type; criterion = getInstance(type, null); presetModel = new PresetModel(this, type); try{ beanInfo = org.openide.util.Utilities.getBeanInfo(type); if (hasCustomizer()) { customizer = getCustomizer(); customizerComponent = (Component) customizer; } else { // TODO use property sheet as it will implement Customizer // allow hiding tabs, .... System.err.println("No custonizer for " + criterion.getName() + ", skipping..."); } } catch (java.beans.IntrospectionException ex) { if (Boolean.getBoolean ("netbeans.debug.exceptions")) // NOI18N ex.printStackTrace(); } customizer.setObject(criterion); criterion.addPropertyChangeListener(this); } public boolean hasCustomizer () { // true if we have already computed beanInfo and it has customizer class return beanInfo.getBeanDescriptor ().getCustomizerClass () != null; } /** * Get name of this criterion used as tab name, * it is mangled if the criterion is modified. * @return my name. */ public String getName() { String name; if (criterion.getTabText() == null) name = criterion.getDisplayName(); else name = criterion.getTabText(); if (isModified()) return name + MODIFICATOR_SUFFIX; //NOI18N else return name; } /** @return relaled customizer compoment. */ public Component getComponent() { return customizerComponent; } /** */ public Customizer getCustomizer() { if (customizer != null) return customizer; Class clazz = beanInfo.getBeanDescriptor ().getCustomizerClass (); if (clazz == null) return null; Object o; try { o = clazz.newInstance (); } catch (InstantiationException e) { return null; } catch (IllegalAccessException e) { return null; } if (!(o instanceof java.awt.Component) || !(o instanceof java.beans.Customizer)) return null; return (Customizer) o; } public CriteriaModel getParent() { return parent; } public PresetModel getPresetModel() { return presetModel; } public Class getCriterionClass() { return criterion.getClass(); } /** Change customizer value according to preset value. */ public void usePreset(String state) { boolean old = modified; String oldState = this.state; if (state.equals(DO_NOT_APPLY)) { modified = false; } else if (state.equals(APPLY)) { if (oldState.equals(DO_NOT_APPLY)) modified = true; } else { modified = true; criterion = getInstance(type, state); getCustomizer().setObject(criterion); criterion.addPropertyChangeListener(this); } // t("State " + oldState + " -> " + state + " : " + modified); // NOI18N // t("Value " + criterion ); // NOI18N this.state = state; propertyChangeSupport.firePropertyChange( PROP_CUSTOMIZED, old, modified // NOI18N ); propertyChangeSupport.firePropertyChange( PROP_STATE, oldState, state // NOI18N ); } /** @return current state. */ public String getState() { return state; } private String defaultState() { return APPLY; } /** * @return true if new value was created */ public boolean saveAs(String name) throws IllegalArgumentException { boolean flag = true; // protect build in settings if (name.equals(DO_NOT_APPLY) || name.equals(APPLY)) throw new IllegalArgumentException(); criterion.setName(name); // overwrite existing if (Registry.exist(criterion)) { Registry.remove(criterion); flag = false; } Registry.append(criterion); return flag; } public void propertyChange(PropertyChangeEvent event) { if (event.getSource() == criterion) { boolean old = modified; // if Type fires valid property change listens for // its invalidity -> mark itself as unmodified if (SearchType.PROP_VALID.equals(event.getPropertyName()) ) { if (event.getNewValue().equals(new Boolean(false))) { modified = false; propertyChangeSupport.firePropertyChange ( PROP_CUSTOMIZED, old, modified // NOI18N ); } } else { //any modification -> modified = true modified = true; propertyChangeSupport.firePropertyChange ( PROP_CUSTOMIZED, old, modified // NOI18N ); if (state.equals(DO_NOT_APPLY)) propertyChangeSupport.firePropertyChange ( PROP_STATE, state, defaultState() // NOI18N ); } } } /** This fire no property cange use parent. */ public void addPropertyChangeListener(PropertyChangeListener l) { propertyChangeSupport.addPropertyChangeListener(l); } /** Removes a PropertyChangeListener from the listener list. * @param l The listener to remove. */ public void removePropertyChangeListener(java.beans.PropertyChangeListener l) { propertyChangeSupport.removePropertyChangeListener (l); } public boolean isModified () { return modified; } /** Return currently hold bean. */ public SearchType getCriterion () { return criterion; } /** Class equality * @return this.bean.getClass().equals(bean.getClass()); */ public boolean equals(Object obj) { try { return criterion.getClass().equals(((CriterionModel)obj).getCriterionClass()); } catch (ClassCastException ex) { return false; } } /** * @param type class os SearchType which instance is required * @param name of instance (from control panel) * @return preset instance of search type or default instance if not found */ private SearchType getInstance(Class type, String name) { // use named instance if ( type != null ) { Enumeration en = TopManager.getDefault().getServices().services(type); while (en.hasMoreElements()) { SearchType next = (SearchType) en.nextElement(); if (next.getName().equals(name)) { return (SearchType) next.clone(); } } } // otherwise use default instance Object ret = null; try { ret = type.newInstance(); } catch (InstantiationException ex) { // ignore such search type if (Boolean.getBoolean ("netbeans.debug.exceptions")) // NOI18N ex.printStackTrace(); } catch (IllegalAccessException ex) { // ignore such search type if (Boolean.getBoolean ("netbeans.debug.exceptions")) // NOI18N ex.printStackTrace(); } return (SearchType) ret; } public boolean isInitialized() { return parent.isInitialized(); } public String toString() { return "CriterionModel: " + type + " state:" + state + criterion; // NOI18N } public HelpCtx getHelpCtx() { return criterion.getHelpCtx(); } } /* * Log * 9 Gandalf-post-FCS1.5.2.2 4/4/00 Petr Kuzel Comments + output window * fix * 8 Gandalf-post-FCS1.5.2.1 3/9/00 Petr Kuzel I18N * 7 Gandalf-post-FCS1.5.2.0 2/24/00 Ian Formanek Post FCS changes * 6 Gandalf 1.5 1/13/00 Radko Najman I18N * 5 Gandalf 1.4 1/12/00 Petr Kuzel Html tag removed. * 4 Gandalf 1.3 1/10/00 Petr Kuzel Buttons enabling. * 3 Gandalf 1.2 1/5/00 Petr Kuzel Margins used. Help * contexts. * 2 Gandalf 1.1 1/4/00 Petr Kuzel Bug hunting. * 1 Gandalf 1.0 12/23/99 Petr Kuzel * $ */